﻿using DongFangGuoKai.WMS.IApiService;
using DongFangGuoKai.WMSPlatform.Commn.ExtendModule;
using DongFangGuoKai.WMSPlatform.Core;
using DongFangGuoKai.WMSPlatform.Domain.AGVModels;
using DongFangGuoKai.WMSPlatform.Domain.Enums;
using DongFangGuoKai.WMSPlatform.Domain.Models;
using DongFangGuoKai.WMSPlatform.Service.BasicApp.Pallet.DTO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;

namespace DongFangGuoKai.WMSPlatform.Service.BasicApp.Pallet
{
    public class PalletService : IPalletService
    {
        private readonly Repository<t_Pallet> palletrepost;
        private readonly Repository<t_Cell> cellrepost;
        private readonly IAGVService aGVService;
        private readonly Repository<t_Instruct> instructrepost;

        public PalletService(Repository<t_Pallet> palletrepost,
            IAGVService aGVService
            )
        {
            cellrepost = palletrepost.ChangeRepository<Repository<t_Cell>>();
            instructrepost = palletrepost.ChangeRepository<Repository<t_Instruct>>();

            this.palletrepost = palletrepost;
            this.aGVService = aGVService;
        }

        /// <summary>
        /// 批量添加托盘
        /// </summary>
        /// <param name="addListPalletDTO"></param>
        /// <param name="errMsg"></param>
        /// <returns></returns>
        public bool AddPalletList(AddListPalletDTO addListPalletDTO, out string errMsg)
        {
            errMsg = string.Empty;
            string name = "";
            string code = "";
            string LogicalPartCode = "";
            if (addListPalletDTO.Type == 0)
            {
                code = "A";
                name = "托盘-";
                LogicalPartCode = "PalletArea";
            }
            else if (addListPalletDTO.Type == 1)
            {
                code = "B";
                name = "大料箱-";
                LogicalPartCode = "BulkyArea";
            }
            else if (addListPalletDTO.Type == 2)
            {
                code = "C";
                name = "小料箱-";
                LogicalPartCode = "SmallArea";
            }
            try
            {
                palletrepost.AsTenant().BeginTran();
                int pallnum;
                var pallList = palletrepost.GetList(p => p.Type == addListPalletDTO.Type);
                if (pallList is null || pallList.Count() <= 0)
                {
                    pallnum = 10001;
                }
                else
                {
                    var pall = pallList.OrderByDescending(p => p.DisplayOrder).FirstOrDefault();
                    pallnum = Convert.ToInt32(pall.PalletBarcode.Substring(1))+1;
                }
                for (int i = 0; i < addListPalletDTO.Num; i++)
                {
                    
                    t_Pallet pallet = new t_Pallet()
                    {
                        PalletBarcode = code + pallnum,
                        PalletName = name + pallnum,
                        DisplayOrder = pallnum,
                        Status = 1,
                        LocationCode = "",
                        LocationName = "",
                        ERPLocationName = "",
                        LogicalPartCode = LogicalPartCode,
                        Type = addListPalletDTO.Type,
                        CreateDate = DateTime.Now
                    };

                    if (!palletrepost.Insert(pallet))
                    {
                        errMsg = "批量添加托盘失败，终止添加的托盘为：" + pallet.PalletBarcode;
                        palletrepost.AsTenant().CommitTran();
                        return false;
                    }
                    pallnum++;
                }
                errMsg = "添加成功";
                palletrepost.AsTenant().RollbackTran();
                return true;
            }
            catch (Exception ex)
            {
                errMsg = ex.Message;
                palletrepost.AsTenant().RollbackTran();
                return false;
                throw;
            }
            
        }

        /// <summary>
        /// 托盘储位绑定
        /// </summary>
        /// <param name="bindPalletCellDTO"></param>
        /// <returns></returns>
        public bool BindPalletCell(BindPalletCellDTO bindPalletCellDTO, out string errMsg)
        {
            errMsg = string.Empty;
            var pall = palletrepost.GetFirst(p => p.PalletBarcode == bindPalletCellDTO.PalletCode && p.Status == 1);
            if (pall is null)
            {
                errMsg = "未查询到箱号或托盘：" + bindPalletCellDTO.PalletCode;
                return false;
            }
            if (!string.IsNullOrEmpty(pall.LocationCode))
            {
                errMsg = "箱号或托盘已在储位";
                return false;
            }

            var cell = cellrepost.GetFirst(c => c.Code == bindPalletCellDTO.CellCode && c.Status == 1);

            if (cell is null)
            {
                errMsg = "储位状态非正常:" + bindPalletCellDTO.CellCode;
                return false;
            }

            if (palletrepost.GetList(p => p.LocationCode == bindPalletCellDTO.CellCode).Count() != 0)
            {
                errMsg = "托盘已在储位上：" + bindPalletCellDTO.PalletCode;
                return false;
            }

            pall.LocationCode = cell.Code;
            pall.LocationName = cell.Name;
            pall.ERPLocationName = cell.ERPCode;
            if (!palletrepost.Update(pall))
            {
                errMsg = "绑定失败";
                return false;
            }

            cell.BusinessType = 0;
            cell.IsLock = true;
            cell.FullStatus = 0;
            cell.Status = 2;
            cell.ModifyDate = DateTime.Now;
            if (!cellrepost.Update(cell))
            {
                errMsg = "更新仓位货位信息失败";
                return false;
            }

            errMsg = "绑定成功";
            return true;
        }


        /// <summary>
        /// 托盘储位绑定
        /// </summary>
        /// <param name="bindPalletCellDTO"></param>
        /// <returns></returns>
        public bool BindPalletCell2(BindPalletCellDTO bindPalletCellDTO, out string errMsg)
        {
            errMsg = string.Empty;
            var pall = palletrepost.GetFirst(p => p.PalletBarcode == bindPalletCellDTO.PalletCode && p.Status == 1);
            if (pall is null)
            {
                errMsg = "未查询到箱号或托盘：" + bindPalletCellDTO.PalletCode;
                return false;
            }
            if (!string.IsNullOrEmpty(pall.LocationCode))
            {
                errMsg = "箱号或托盘已在储位";
                return false;
            }

            var cell = cellrepost.GetFirst(c => c.Code == bindPalletCellDTO.CellCode && c.Status == 1);

            if (cell is null)
            {
                errMsg = "未查询到储位:" + bindPalletCellDTO.CellCode;
                return false;
            }

            if (palletrepost.GetList(p => p.LocationCode == bindPalletCellDTO.CellCode).Count() != 0)
            {
                errMsg = "托盘已在储位上：" + bindPalletCellDTO.PalletCode;
                return false;
            }

           
            var taskRes = AGVTest(pall.PalletBarcode, pall.Type.GetValueOrDefault(),cell.ERPCode, bindPalletCellDTO.TargetCellCode);

            if (taskRes)
            {
                pall.LocationCode = cell.Code;
                pall.LocationName = cell.Name;
                pall.ERPLocationName = cell.ERPCode;
                if (!palletrepost.Update(pall))
                {
                    errMsg = "绑定失败";
                    return false;
                }


                errMsg = "绑定成功";
            }

            return true;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="palletCode">托盘条码</param>
        /// <param name="palletType">托盘类型</param>
        /// <param name="erpCode">起点的avg地址</param>
        /// <param name="targetCellCode">终点：wms仓位Code</param>
        /// <returns></returns>
        private bool AGVTest(string palletCode, int palletType,string erpCode,string targetCellCode)
        {
            Console.WriteLine($"起点：{erpCode}");
            (string avgPalletType,string avgTaskType) = SwitchType(palletType);
            if (string.IsNullOrEmpty(avgPalletType))
            {
                return false;
            }

            //绑定
            BindCtnrAndBinModel bindCtnrAndBinModel = new BindCtnrAndBinModel();

            var uuid = Guid.NewGuid();
            bindCtnrAndBinModel.reqCode = uuid.ToString("N");
            bindCtnrAndBinModel.taskCode = bindCtnrAndBinModel.reqCode;
            bindCtnrAndBinModel.reqTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

            //绑定用户
            bindCtnrAndBinModel.clientCode = "PDA";
            //绑定容器类型 大容器类型
            bindCtnrAndBinModel.ctnrTyp = avgPalletType;
            //banging起始目标储位  
            bindCtnrAndBinModel.stgBinCode = erpCode;
            //绑定
            bindCtnrAndBinModel.indBind = "1";

            var res = aGVService.BindCntrAndUnBindTask(bindCtnrAndBinModel);
            Console.WriteLine("绑定："+res.ToJson());

            //添加任务单
            AddTaskModel addTaskModel = new AddTaskModel();
            addTaskModel.reqCode = Guid.NewGuid().ToString("N");
            addTaskModel.clientCode = "PDA";
            //ARM入库出库
            addTaskModel.TaskTyp = avgTaskType;

            var taskCode = Guid.NewGuid();
            //叉车对应的大容器类型
            addTaskModel.CtnrTyp = avgPalletType;
            addTaskModel.taskCode = taskCode.ToString();

            var cell = cellrepost.GetFirst(c => c.Status == 1 && c.Code == targetCellCode);
            //任务起始点仓位编码
            addTaskModel.PositionCodePath = new PositionCodePathDto[2] {
                    new PositionCodePathDto() {
                        //叉车实际位置
                        PositionCode=erpCode,// 起始地址 D00080A2502013
                        Type="05"//固定05
                    },
                    //实际传入编号，测试传入仓位
                    new PositionCodePathDto() {
                        PositionCode=cell.ERPCode,//ERP目标地址
                        Type="05"
                    }
                };

            var res2 = aGVService.CreateTask(addTaskModel);
            Console.WriteLine("任务入参："+addTaskModel.ToJson());
            Console.WriteLine("任务："+res2.ToJson());

            var instruct = new t_Instruct
            {
                //WarehouseCode = stackingstorage.WarehouseCode,
                Status = 2,
                ToLocation = "",
                //StackingStorageId = stackingStorageId,//换成code
                //StackingStorageCode = stacking.Code,
                WorkDeviceType = EmWorkDeviceType.AGV,
                InstructType = EmInstructType.In,
                Action = EmDeviceAction.Transport,
                //RelatedOrderDetailId = orderDetail.Id,//换成code
                //RelatedOrderDetailCode = shippingorder.OutBoundNo,
                DeviceCode = "",
                ExpectedToLocation = cell.Code,
                InstructIndex = 1,
                PalletBarcode = palletCode,
                ScanedBarcode = palletCode,
                Priority = 9999,
                //Qty = materialNum.GetValueOrDefault(),
                FinishedQTY = 0,
                LogicalCellAddr = cell.ERPCode,
                StartTime = DateTime.Now,
                BusinessGroupId = taskCode,
                BusinessType = (int)EmBusinessType.In,
                //BillType = (int)orderDetail.BillType.GetValueOrDefault(),

            };
            instructrepost.Insert(instruct);
            return res2.code == "0";

        }
        /// <summary>
        /// 把WMS的容器类型转换为AGV的容器类型
        /// </summary>
        /// <param name="wmsType"></param>
        /// <returns></returns>
        private (string,string) SwitchType(int wmsType)
        {
            switch (wmsType)
            {
                case 0:
                    return ("3","B1");
                case 1:
                    return ("2","A11");
                case 2:
                    return ("1", "A10");
                default:
                    return (null,null);
            }
        }
        /// <summary>
        /// 查询所有托盘
        /// </summary>
        /// <param name="name"></param>
        /// <param name="type"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="totalCount"></param>
        /// <returns></returns>
        public List<t_Pallet> GetPallets(string name, int type, int pageIndex, int pageSize, out int totalCount)
        {
            var list = palletrepost.GetList();
            if (!string.IsNullOrEmpty(name))
            {
                list = list.Where(x => x.PalletName.Contains(name)).ToList();
            }
            if (type != -1)
            {
                list = list.Where(x => x.Type == type).ToList();
            }
            totalCount = list.Count();
            list = list.OrderByDescending(x => x.CreateDate).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
            return list;
        }
        /// <summary>
        /// AGV入库完成 改变托盘所在仓位
        /// </summary>
        /// <param name="palletCode">托盘条码</param>
        /// <param name="cellCode">所在仓位</param>
        /// <param name="errMsg"></param>
        /// <returns></returns>
        public bool UpdPalletCellCode(string palletCode, string cellCode, out string errMsg)
        {
            errMsg = string.Empty;
            var pallet = palletrepost.GetFirst(s=>s.PalletBarcode==palletCode);
            if (pallet == null)
            {
                errMsg = $"找不到托盘信息,{palletCode}";
                return false;
            }
            var cell = cellrepost.GetFirst(s=>s.Code==cellCode);
            if (cell == null)
            {
                errMsg = $"找不到仓位信息,{cellCode}";
                return false;
            }
            pallet.LocationName = cell.Name;
            pallet.LocationCode = cell.Code;
            pallet.ERPLocationName = cell.ERPCode;
            return palletrepost.Update(pallet);
        }

        /// <summary>
        /// 托盘打印
        /// </summary>
        /// <param name="codes"></param>
        /// <param name="errMsg"></param>
        /// <returns></returns>
        public bool PallPrintCount(string[] codes, out string errMsg)
        {
            errMsg = string.Empty;
            if (codes.Count() <= 0)
            {
                errMsg = "Id有误";
                return false;
            }
            try
            {
                palletrepost.AsTenant().BeginTran();
                foreach (string code in codes)
                {
                    var pall = palletrepost.GetFirst(p => p.PalletBarcode == code);
                    if (pall == null)
                    {
                        palletrepost.AsTenant().RollbackTran();
                        errMsg = "未查询出托盘";
                        return false;
                    }
                    pall.PrintTimes = pall.PrintTimes + 1;
                    if (!palletrepost.Update(pall))
                    {
                        palletrepost.AsTenant().RollbackTran();
                        errMsg = "修改箱号或托盘打印次数失败！";
                        return false;
                    }
                }
                palletrepost.AsTenant().CommitTran();
                errMsg = "修改打印次数成功";
                return true;
            }
            catch (Exception ex)
            {
                palletrepost.AsTenant().RollbackTran();
                errMsg = ex.Message;
                return false;
                throw;
            }
            
        }
    }
}
